Einführung in die Programmierung

Compilersprachen vs Interpretersprachen

Compilersprachen:
  • Compiler übersetzt Quelltext in Maschinencode
  • Maschinencode ist nur von jeweiligem Betriebssystem ausführbar
  • Beispiel: Quelle.c \rightarrow Quelle.exe
  • Interpretersprachen:
  • Interpreter lässt Quelltext direkt ausführen
  • Quelltext ist auf jedem Betriebssystem ausführbar, auf dem der Interpreter verfügbar ist
  • Compilersprachen vs Interpretersprachen

    Aufgabe 1: Informiere dich im Internet über die Vor- und Nachteile von Compilersprachen bzw. Interpretersprachen
    Aufgabe 2: Suche im Internet nach Beispielen für Compilersprachen bzw. Interpretersprachen
    Aufgabe 3: Informiere dich im Internet darüber, wie Java und Python zuzuordnen sind

    Java Installation

  • Um Java-Programme zu schreiben benötigt man das Java Development Kit (JDK)
  • Zum Ausführen von Java-Programmen reicht die Java Runtime Environment (JRE)
  • Beides ist auf java.com kostenlos verfügbar
  • Java Programmierung

  • Nach Installation des JDK kann eine Java-Datei mit der Endung .java in der Kommandozeile mit dem Befehl “javac dateiname.java” kompiliert werden
  • Mit “java dateiname” kann das kompilierte Programm ausgeführt werden
  • Java Programmierung

  • Zur Erstellung von Java-Dateien reicht ein Texteditor
  • Integrierte Entwicklungsumgebungen (IDE) bieten hilfreiche Zusatzfunktionen zum fortgeschrittenen Programmieren
  • Beispiele sind Eclipse, Netbeans oder zum Lernen der Java-Editor
  • Programmaufbau

    public class Klassenname{
      public static void main(String[] args){
        Definitionen und Anweisungen; //Hier beginnt das Programm
      }
    }

    Beispiel:

    public class Hallo{
      public static void main(String... args){
        System.out.println("Hallo in meinem ersten Programm");
      }
    }

    Pakete importieren

    Statt das Rad neu zu erfinden, kann es auch importiert werden:
    Beispiel für Nachrichtenfenster:

    import javax.swing.JOptionPane;
    public class Nachrichtenfenster{
      public static void main(String... args){
        JOptionPane.showMessageDialog(null, "Hallo im Nachrichtenfenster");
      }
    }

    Klassen

  • Ein Java-Programm besteht aus mindestens einer “Klasse”
  • Die KlassenDefinition beginnt mit den Wörtern “public class” gefolgt vom Klassennamen
  • Klassenname=Dateiname
  • Konventionell beginnen Klassennamen mit einem Großbuchstaben und jedes weitere Wort folgt ohne Leerzeichen beginnend mit Großbuchstaben (CamelCase-Notation)
  • Datentypen

    Typ Wertebereich Beispiel
    Ganze Zahlen
    byte -128…127 123
    short -32768…32767 1234
    int -2\cdot 10^9...2\cdot 10^9 12345
    long -10^{19}...10^{19} 123456L
    Gleitkommazahlen
    float -10^{38}...10^{38} 1.2f
    double -10^{308}...10^{308} 1.2
    Wahrheitswert
    boolean {true, false} true
    Zeichen
    char Unicode Zeichen ‘c’
    Zeichenkette
    String “Hallo”

    Anweisungen, Definitionen, Deklarationen und Initialisierungen

  • Ein Programm besteht insbesondere aus Anweisungen, d.h. Befehlen, und Definitionen
  • Anweisungen werden nacheinander abgearbeitet
  • Anweisungen werden mit einem Semikolon abgeschlossen
  • Definitionen legen u.a. Bezeichner und Datentyp einer Variablen fest und reservieren entsprechenden Speicherplatz
  • Deklarationen machen dem Programm ebenfalls Variablen bekannt, reservieren aber keinen Speicherplatz
  • Wird einer Variablen erstmalig ein Wert zugeordnet, spricht man von einer Initialisierung
  • Definition und Initialisierung

    Definition einer Variablen:

    //<Datentyp> <Bezeichner>;
    int zahl;

    Initialsierung (Zuweisung):

    //<Bezeichner> = <Wert>;
    zahl = 1;

    Definition und Initialisierung:

    //<Datentyp> <Bezeichner> = <Wert>;
    int zahl = 1;

    Kommentare

  • Um Programme lesbarer zu machen, können Kommentare eingefügt werden, die vom Compiler ignoriert werden
  • // … ist ein einzeiliger Kommentar, der mit dem Zeilenende endet
  • /* … */ ist ein mehrzeiliger Kommentar
  • /** … */ ist ein mehrzeiliger Dokumentationskommentar vor Definitionen
  • Definition und Initialisierung (Übung)

    1. Öffne das Programm DefinitionUndInitialisierung.java und schreibe als Kommentar hinter der jeweiligen Zeile, ob eine Definition oder eine Initialisierung vorliegt.
    2. Öffne das Programm SelbstDefinierenUndZuweisen.java und setze die Kommentare um.

    Blöcke

  • Anweisungen können zu einem Block zusammengefasst werden
  • Blöcke werden durch geschweifte Klammern umschlossen und sollten eingerückt werden
  • Zwei Konventionen zur Platzierung der Klammern sind verbreitet:
  • public class Willkommen{
      ...
    }
    
    public class Willkommen
    {
      ...
    }

    Strings und Texte

  • Strings sind Ketten von Zeichen
  • In Anführungszeichen gesetzter Text wird als String definiert
  • Neue Zeilen können durch \n erzeugt werden
  • Mit der Anweisung System.out.println(“…”) kann Text in der Konsole ausgegeben werden
  • Strings und Variablen können mit einem + miteinander verbunden werden, z.B. System.out.println(“hier steht der Text von”+name)
  • Strings können durch string1.equals(string2) verglichen werden
  • Texte einlesen

    import java.util.Scanner;
    public class Text{
      public static void main(String[] args){
        Scanner in = new Scanner(System.in);
        String text = in.nextLine(); //liest die nächste Zeile ein
        int i = in.nextInt(); //liest die nächste Zeile als Zahl ein
        int j = in.nextInt();
        System.out.println(i+j);
      }
    }

    Operatoren

    Numerische Operatoren Logische Operatoren
    + Addition == Gleichheit
    Subtraktion != Ungleichheit
    * Multiplikation < kleiner als
    / Division <= kleiner gleich
    % Modulo (Rest einer Division) > größer als
    ++ Inkrement >= größer gleich
    += Inkrement und Zuweisung ! nicht
    – – Dekrement && UND
    –= Dekrement und Zuweisung || ODER
    (…) Klammerung

    Bedingte Anweisungen und Verzweigungen

    //Bedingte Anweisung:
    if(bedingung){
      //Anweisungen, die ausgeführt werden, wenn bedingung true ist
    }
    //Anweisungen, die unabhängig von bedingung nach der bedingten Anweisung ausgeführt wird
    
    //Verzweigung
    if(bedingung){
      //Anweisungen, die ausgeführt werden, wenn bedingung true ist
    }else{
      //Anweisungen, die ausgeführt werden, wenn bedingung false ist
    }
    //Anweisungen, die unabhängig von bedingung nach der Verzweigung ausgeführt wird

    Übungsaufgabe Chatbot

    Aufgabe: Schreibe einen Chatbot, der mit dem Nutzer chattet. Sorge durch sinnvolle Variablen und Kommentare dafür, dass das Programm für Andere leicht nachzuvollziehen ist und achte auf die besprochenen Konventionen. Der Dateiname soll dein Name sein.

    Der Chatbot / das Programm sollte folgendes erfüllen:
  • Jede Ausgabe des Chatbots soll mit “Chatbot:” starten
  • Das Programm startet mit der Aufforderung an den Nutzer, den Chatbot zu begrüßen
  • Das Programm liest die Begrüßung mithilfe der Scannerklasse ein
  • Der Chatbot begrüßt den Nutzer mit den selben Worten
  • Der Chatbot fragt den Nutzer nach seinem Namen und verwendet den Namen fortan
  • Der Chatbot stellt einige Ja/Nein-Fragen, die der Nutzer mit “Ja” oder “Nein” beantwortet
  • Abhängig von der Antwort des Nutzers, soll der Chatbot die Antwort kommentieren
  • Der Chatbot fragt nach dem Alter des Nutzers in Jahren
  • Der Chatbot fragt nach einer Schätzung des Nutzers, wie viele Tage das sind
  • Der Chatbot berechnet, ob der Nutzer richtig, zu hoch oder zu niedrig geschätzt hat und antwortet entsprechend
  • Der Chatbot verabschiedet sich und das Programm wird beendet
  • Schleifen

  • Kontrollstrukturen, um Anweisungs-Blöcke zu wiederholen
  • Man unterscheidet:
  • Zählschleifen (For-Schleifen)
  • Kopfgesteuerte Schleifen (While-Do-Schleifen)
  • Fußgesteuerte Schleifen (Do-While-Schleifen)
  • Mengenschleifen (Foreach-Schleifen)
  • Zählschleifen (For-Schleifen)

    for(INITIALISIERUNG; BEDINGUNG; AKTUALISIERUNG){} ANWEISUNGEN; }

    Beispiel:

    int summeVon0Bis9 = 0;
    for(int i=0; i<10; i++){
      summeVon0Bis9 += i;
    }
  • Initialsierung: Zählvariable wird initialisiert
  • Bedingung: Schleife wird wiederholt, bis die Bedingung nicht mehr erfüllt ist
  • Aktualisierung: Zählvariable wird aktualisiert
  • Kopfgesteuerte Schleifen (While-Do-Schleifen)

    while(BEDINGUNG){ ANWEISUNGEN; }

    Beispiel:

    int summeVon0Bis9 = 0;
    int i = 0;
    while(i<10){
      summeVon0Bis9 += i;
      i++;
    }
  • Schleife wird nur durchlaufen, wenn die Bedingung erfüllt ist
  • Schleife wird wiederholt, bis die Bedingung nicht mehr erfüllt ist
  • Initialisiert wird ggfs. vor der Schleife
  • Aktualisiert wird ggfs. innerhalb der Schleife
  • Fußgesteuerte Schleifen (Do-While-Schleifen)

    do{ ANWEISUNGEN; }(BEDINGUNG);

    Beispiel:

    int i = 0;
    int summeVon0Bis9 = 0;
    do{
      summeVon0Bis9 += i;
      i++;
    }while(i<10);
  • Schleife wird mindestens einmal durchlaufen, unabhängig von der Bedingung
  • Schleife wird wiederholt, bis die Bedingung nicht mehr erfüllt ist
  • Initialsiert wird ggfs. vor der Schleife
  • Aktualisiert wird ggfs. innerhalb der Schleife
  • Mengenschleifen (Foreach-Schleifen)

    for(TYP ELEMENT : KOLLEKTION){ ANWEISUNGEN; }

    Beispiel:

    int[] numbers = {0,1,2,3,4,5,6,7,8,9};
    int summeVon0Bis9 = 0;
    for(int i : numbers){
      summeVon0Bis9 += i;
    }
  • Schleife wird für jedes Element einer Menge (z.B. Array oder Liste) durchgeführt
  • Übungsaufgabe Schleifen

    Verwende jeweils die ersten drei Schleifenarten und beschreibe jeweils Vor- und Nachteile.
    1. Gib die Zahlen von 1000 bis 0 in der Konsole aus.
    2. Berechne mithilfe einer Schleife 10! und gib das Ergebnis in der Konsole aus.
    3. Gib das kleine Einmaleins in der Konsole aus:
      • 1 x 1 = 1
      • 1 x 2 = 2
      • 10 x 10 = 100

    Übungsaufgabe Verflixte Sieben

    Ein in der Grundschule und in der Sekundarstufe 1 beliebtes Mathespiel ist die verflixte Sieben.
    Dabei zählt man reihum von 1 beginnend aufwärts, aber lässt jede Zahl aus, die durch die 7 teilbar ist oder die 7 als Ziffer enthält.
    Also: 1,2,3,4,5,6,8,…,13,15,16,18…
    Erstelle ein Programm das auf diese Weise von 1 bis 1000 zählt.
    Dabei ist der Modulo Operator % und die Funktion STRINGVARIABLENNAME.contains(“ZEICHENKETTE, DIE ENTHALTEN SEIN SOLL”) nützlich.

    Arrays

  • Ein Array (Feld) ist eine Datenstruktur, die mehrere Daten vom selben Typ speichert
  • Der Zugriff erfolgt über Indizes
  • Beispiel:
  • Statt name0=“Max”, name1=“Hans”, name2=“Petra” benutzen wir ein Array zum Speichern der Vornamen einer Namensliste
  • Dann ist namen[0]=“Max”, namen[1]=“Hans”, namen[2]=“Petra”
  • Durch den Zugriff durch Indizes ist z.B. der Zugriff auf die Variablen innerhalb von Schleifen deutlich leichter
  • Aufbau von Arrays

    DATENTYP[] ARRAYVARIABLENNAME = new DATENTYP[LÄNGEDESARRAYS];

    Die leeren eckigen Klammern dürfen auch hinter dem Arrayvariablennamen stehen:

    DATENTYP ARRAYVARIABLENNAME[] = new DATENTYP[LÄNGEDESARRAYS];

    Der Inhalt des Arrays kann bereits bei der Definition des Arrays initialisiert werden:

    DATENTYP[] ARRAYVARIABLENNAME = {ELEMENT0, ELEMENT1, ..., ELEMENTN};

    Array Beispiel Namensliste

    String[] namen = new String[3]; //Array wird deklariert
    namen[0] = "Max"; //Der Inhalt an der Stelle 0 des Arrays wird initialisiert
    namen[1] = "Hans";
    namen[2] = "Petra";
    System.out.println("Der erste Name in der Liste ist " + namen[0]); //Der erste Name wird in der Konsole ausgegeben

    Array Beispiel Namensliste

    String[] namen = {"Max", "Hans", "Petra"}; //Array wird deklariert und sein Inhalt gleichzeitig initialisiert, die Länge ergibt sich damit automatisch
    System.out.println("Der erste Name in der Liste ist " + namen[0]); //Der erste Name wird in der Konsole ausgegeben

    Weitere Beispiele

    boolean[] istMaennlich = new boolean[3];
    istMaennlich[0] = true;
    istMaennlich[1] = true;
    istMaennlich[2] = false;
    int[] alter = {16, 17, 16};
    System.out.println(namen[0] + " ist " + alter[0] " Jahre alt."); //Max ist 16 Jahre alt.
    if(istMaennlich[0]){  //Wenn die erste Person in der Liste männlich ist, wird dies so ausgegeben.
      System.out.println(namen[0] + " ist männlich.");
    }else{ //ansonsten wird ausgegeben, dass sie weiblich ist.
      System.out.println(namen[0] + " ist weiblich.");
    }

    Länge eines Arrays

  • Arrays haben immer eine bestimmte Länge
  • Die Länge kann durch ARRAYVARIABLENNAME.length abgerufen werden
  • Zugriff über einen Index, der kleiner als 0 ist oder größer oder gleich der Länge des Arrays ist, führt zu einem Fehler
  • Mehrdimensionale Arrays (Matrizen)

  • Mit Arrays können auch Matritzen realisiert werden
  • Beispiel: Bilddarstellung an einem Full HD-Monitor, wobei der gespeicherte int-Wert die Farbe codiert, die an dem Pixel dargestellt wird, der durch die Indizes beschrieben wird
  • int[][] bild = new int[1080][1920]
  • Beispiel Mehrdimensionale Arrays

    int[][] matrix = new int[3][4];
    matrix[0][0] = 1;
    matrix[0][1] = 2;
    ...
    matrix[2][3] = 12;

    die gleiche Matrix erzeugt auch

    int[][] matrix = new int[3][4];
    int[] zeile0 = {1,2,3,4};
    int[] zeile1 = {5,6,7,8};
    int[] zeile2 = {9,10,11,12};
    matrix[0] = zeile0;
    matrix[1] = zeile1;
    matrix[2] = zeile2;

    oder

    int[][] matrix = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

    Übungsaufgabe Primzahlenfinder

    Eine Primzahl ist eine natürliche Zahl, die durch genau zwei verschiedene natürliche Zahlen teilbar ist. Anders ausgedrückt ist eine Primzahl eine natürliche Zahl, die nur durch sich selbst und die Zahl 1 teilbar ist, mit Außnahme der 1 selbst.
    1. Schreibe ein Programm, das die ersten 100 Primzahlen findet, in einem Array speichert und das Array am Ende ausgibt.
    Um zu ermitteln, ob eine natürliche Zahl x eine Primzahl ist, kann man x durch jede natürliche Zahl kleiner als x teilen und überprüfen, ob ein Rest übrig bleibt.
    Dabei kann der Modulo-Operator % nützlich sein, der den Rest zurückgibt der beim Teilen von zwei Zahlen übrig bleibt.
    2. Finde und implementiere einen Algorithmus, der effizienter arbeitet, als der eben beschriebene Algorithmus, indem nicht jede kleinere Zahl als x überprüft wird, sondern nur die nötigen.

    Motivation für Methoden

    • Methoden helfen, das Programm übersichtlicher zu machen
    • Methoden helfen, Code wiederzuverwenden
    • Methoden helfen, Programmierarbeit aufzuteilen

    Verwendung von Methoden

    • Methoden können einen direkten Effekt haben, aber kein Ergebnis liefern (Schlüsselwort void), z.B. gibt System.out.println(“Hallo”) Text aus, aber liefert kein Ergebnis
    • Methoden können keinen direkten Effekt haben, aber ein Ergebnis liefern, z.B. kann eine Methode add(a,b) keinen Effekt haben, aber das Ergebnis a+b liefern
    • Methoden können einen direkten Effekt haben und ein Ergebnis liefern, z.B. könnte eine Methode print(array) das Array ausgeben und als Ergebnis in einem Boolean liefern, ob das Array leer war oder tatsächlich etwas ausgegeben werden konnte

    Aufbau von Methoden

    public static RÜCKGABETYP METHODENNAME(PARAMETER){
      ANWEISUNGEN;
      return RÜCKGABEWERT;
    }
    • Der Rückgabetyp ist der Datentyp des Ergebnisses (z.B. int, boolean, double, String)
    • Gibt die Methode kein Ergebnis zurück, ist der Rückgabetyp void
    • Der Methodenname ist ein beliebiger Name der Methode, der die Konventionen erfüllt (kleiner Anfangsbuchstabe, CamelCase)
    • Es können beliebig viele Parameter (Variablen, die beim Aufruf übergeben werden) verwendet werden, die mit Kommas getrennt sind
    • Der Datentyp muss vor dem Parameternamen angegeben werden
    • Es können beliebig viele Anweisungen im Codeblock folgen
    • return beendet die Methode und gibt den Rückgabewert als Ergebnis zurück
    • Bei Methoden ohne Ergebnis muss kein return angegeben werden

    Platzierung von Methodendefinitionen

    public class KLASSENNAME{
      public static void main(String[] args){
        ANEISUNGEN;
      }
      
      public static RÜCKGABETYP METHODENNAME(PARAMETER){
        ANWEISUNGEN;
      }
    }
    • Die Methode wird innerhalb des Klassenblocks, aber außerhalb der main-Methode (und anderen Methoden) definiert

    Beispiel Methode mit Rückgabe

    public class Rechteck{
      public static void main(String[] args){
        int a = 5;
        int b = 7;
        int flaecheninhalt = berechneFlaecheninhalt(a, b);
        System.out.println("Berechnete Fläche: "+flaecheninhalt);
      }
      
      public static int berechneFlaecheninhalt(int x, int y){
        return x*y;
      }
    }

    Beispiel Methode ohne Rückgabe

    public class Hallo{
      public static void main(String[] args){
        String name = "Basler";
        sagHallo(name);
      }
      
      public static void sagHallo(String name){
        System.out.println("Hallo Herr "+name);
      }
    }

    Übungsaufgaben

    Kopiere den folgenden Quelltext und beende die TODOs so, dass ein lauffähiges Programm mit den gewünschten Ergebnissen entsteht.

    public class Mathe{
      public static void main(String[] args){
        int x = 3;
        int y = 5;
        int z = 7;
        //TODO printSolutions wird mit x und y aufgerufen
        int addition = //TODO add wird mit x, y und z aufgerufen
        //TODO addition wird in der Konsole ausgegeben
      }
      
      //die Funktion add wird definiert
      //add hat zwei int Parameter
      public static int add(int a, int b){
        //TODO add gibt die Addition der Parameter zurück
      }
      
      //TODO eine weitere Funktion add wird definiert (gleicher Name wie zuvor, aber drei Parameter)
      //add hat drei int PARAMETER
      //add gibt die Addition der drei Parameter zurück, aber nutzt dafür nicht +, sondern die oben bereits definierte add Funktion
      
      //TODO die Funktion mult wird definiert
      //mult hat zwei int Paramter
      //mult gibt die Multiplikation der Parameter zurück
      
      //TODO sub wird definiert
      //sub hat zwei int Parameter
      //sub gibt die Subtraktion der beiden Parameter zurück
      
      //TODO mod wird definiert
      //mod hat zwei int Parameter
      //mod gibt den Modulo der beiden Paramter zurück
      
      
      //TODO printSolutions wird definiert
      //printSolutions hat zwei int Parameter
      //printSolutions gibt die Ergebnisse aus add, sub, mult und mod der beiden Parameter durch Kommas getrennt auf der Konsole aus
      //z.B. wäre die Ausgabe für printSolutions(1,1) auf der Konsole "2,0,1,0"
      //printSolutions hat nur diesen Effekt, aber kein eigenes Ergebnis, das zurückgegeben wird
    }
    // reveal.js plugins